home *** CD-ROM | disk | FTP | other *** search
/ The Utilities Experience / The Utilities Experience - Volume 1.iso / software / misc / o-z / x-windows / mesa-amiwin / src / span.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-30  |  18.8 KB  |  787 lines

  1. /* span.c */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25. $Id: span.c,v 1.23 1995/11/30 00:19:52 brianp Exp $
  26.  
  27. $Log: span.c,v $
  28.  * Revision 1.23  1995/11/30  00:19:52  brianp
  29.  * make copy of span colors if they may be modified and reused
  30.  *
  31.  * Revision 1.22  1995/10/19  15:49:30  brianp
  32.  * added gamma support
  33.  *
  34.  * Revision 1.21  1995/10/13  22:41:16  brianp
  35.  * removed dithering code, added color/index masking code
  36.  *
  37.  * Revision 1.20  1995/09/18  14:21:29  brianp
  38.  * use NULL mask if writing all pixels in a color span
  39.  *
  40.  * Revision 1.19  1995/08/31  21:33:29  brianp
  41.  * use *DD.read_*_span instead of dd_read_*_span
  42.  *
  43.  * Revision 1.18  1995/07/26  15:03:48  brianp
  44.  * replaced some literals with variables for SunOS 4.x per Asif Khan
  45.  *
  46.  * Revision 1.17  1995/07/24  18:58:10  brianp
  47.  * added CC.ClipSpans logic
  48.  *
  49.  * Revision 1.16  1995/06/12  15:42:53  brianp
  50.  * changed color arrays to GLubyte
  51.  *
  52.  * Revision 1.15  1995/05/31  14:57:36  brianp
  53.  * added gl_read_index_span() and gl_read_color_span()
  54.  *
  55.  * Revision 1.14  1995/05/22  21:02:41  brianp
  56.  * Release 1.2
  57.  *
  58.  * Revision 1.13  1995/05/17  13:52:37  brianp
  59.  * implemented glIndexMask(0) and glColorMask(0,0,0,0)
  60.  *
  61.  * Revision 1.12  1995/05/17  13:17:22  brianp
  62.  * changed default CC.Mode value to allow use of real OpenGL headers
  63.  * removed need for CC.MajorMode variable
  64.  *
  65.  * Revision 1.11  1995/05/12  16:28:09  brianp
  66.  * renamed texture functions
  67.  * added clipping for glDrawPixels
  68.  *
  69.  * Revision 1.10  1995/04/11  14:03:27  brianp
  70.  * changed (*CC.write...) to (*DD.write...)
  71.  *
  72.  * Revision 1.9  1995/03/30  21:06:50  brianp
  73.  * updated to use pointers to CC.write_* functions
  74.  *
  75.  * Revision 1.8  1995/03/27  20:32:17  brianp
  76.  * new Texture.Enabled scheme
  77.  *
  78.  * Revision 1.7  1995/03/08  15:10:02  brianp
  79.  * support for dd_logicop
  80.  *
  81.  * Revision 1.6  1995/03/07  19:02:32  brianp
  82.  * updated for new logic blend function names
  83.  *
  84.  * Revision 1.5  1995/03/07  14:21:14  brianp
  85.  * updated for new XSetForeground/GC scheme
  86.  *
  87.  * Revision 1.4  1995/03/04  19:29:44  brianp
  88.  * 1.1 beta revision
  89.  *
  90.  * Revision 1.3  1995/03/01  17:44:31  brianp
  91.  * added stenciling for PB
  92.  *
  93.  * Revision 1.2  1995/02/27  22:49:03  brianp
  94.  * modified for PB
  95.  *
  96.  * Revision 1.1  1995/02/24  14:28:31  brianp
  97.  * Initial revision
  98.  *
  99.  */
  100.  
  101.  
  102. /*
  103.  * pixel span rasterization:
  104.  * These functions simulate the rasterization pipeline.
  105.  */
  106.  
  107.  
  108. #include <string.h>
  109. #include "alpha.h"
  110. #include "blend.h"
  111. #include "context.h"
  112. #include "depth.h"
  113. #include "dd.h"
  114. #include "fog.h"
  115. #include "gamma.h"
  116. #include "logic.h"
  117. #include "macros.h"
  118. #include "masking.h"
  119. #include "scissor.h"
  120. #include "span.h"
  121. #include "stencil.h"
  122. #include "texture.h"
  123.  
  124.  
  125. #ifndef NULL
  126. #  define NULL 0
  127. #endif
  128.  
  129.  
  130. /*
  131.  * Apply the current polygon stipple pattern to a span of pixels.
  132.  */
  133. static void stipple_polygon_span( GLuint n, GLint x, GLint y, GLubyte mask[] )
  134. {
  135.    register GLuint i, m, stipple, highbit=0x80000000;
  136.  
  137.    stipple = CC.PolygonStipple[y % 32];
  138.    m = highbit >> (GLuint) (x % 32);
  139.  
  140.    for (i=0;i<n;i++) {
  141.       if ((m & stipple)==0) {
  142.      mask[i] = 0;
  143.       }
  144.       m = m >> 1;
  145.       if (m==0) {
  146.      m = 0x80000000;
  147.       }
  148.    }
  149. }
  150.  
  151.  
  152.  
  153. /*
  154.  * Clip a pixel span to the current buffer size.
  155.  * Return:  0 = all pixels clipped
  156.  *          1 = at least one pixel is visible
  157.  */
  158. static GLuint clip_span( GLuint n, GLint x, GLint y, GLubyte mask[] )
  159. {
  160.    GLint i;
  161.  
  162.    /* Clip to top and bottom */
  163.    if (y<0 || y>=CC.BufferHeight) {
  164.       return 0;
  165.    }
  166.  
  167.    /* Clip to left side */
  168.    if (x<0) {
  169.       if (n<=-x) {
  170.      /* completely off left side */
  171.      return 0;
  172.       }
  173.       else {
  174.      for (i=0;i<-x;i++) {
  175.         mask[i] = 0;
  176.      }
  177.       }
  178.    }
  179.  
  180.    /* Clip to right side */
  181.    if (x+n>CC.BufferWidth) {
  182.       i = CC.BufferWidth-x;
  183.       while (i<n)
  184.      mask[i++] = 0;
  185.    }
  186.    return 1;
  187. }
  188.  
  189.  
  190.  
  191. /*
  192.  * Write a horizontal span of color index pixels to the frame buffer.
  193.  * Stenciling, Depth-testing, etc. are done as needed.
  194.  * Input:  n - number of pixels in the span
  195.  *         x, y - location of leftmost pixel in the span
  196.  *         z - array of [n] z-values
  197.  *         index - array of [n] color indexes
  198.  *         primitive - either GL_POINT, GL_LINE, GL_POLYGON, or GL_BITMAP
  199.  */
  200. void gl_write_index_span( GLuint n, GLint x, GLint y, GLint z[],
  201.               GLuint index[], GLenum primitive )
  202. {
  203.    GLuint i;
  204.    GLubyte mask[MAX_WIDTH];
  205.  
  206.    /* init mask to 1's (all pixels are to be written) */
  207.    for (i=0;i<n;i++)
  208.       mask[i] = 1;
  209.  
  210.    if (CC.ClipSpans || primitive==GL_BITMAP) {
  211.       if (clip_span(n,x,y,mask)==0) {
  212.      return;
  213.       }
  214.    }
  215.  
  216.    /* Per-pixel fog */
  217.    if (CC.Fog.Enabled && (CC.Hint.Fog==GL_NICEST || primitive==GL_BITMAP)) {
  218.       gl_fog_index_pixels( n, z, index );
  219.    }
  220.  
  221.    /* Do the scissor test */
  222.    if (CC.Scissor.Enabled) {
  223.       if (gl_scissor_span( n, x, y, mask )==0) {
  224.      return;
  225.       }
  226.    }
  227.  
  228.    /* Polygon Stippling */
  229.    if (CC.Polygon.StippleFlag && primitive==GL_POLYGON) {
  230.       stipple_polygon_span( n, x, y, mask );
  231.    }
  232.  
  233.    if (CC.Stencil.Enabled) {
  234.       /* first stencil test */
  235.       if (gl_stencil_span( n, x, y, mask )==0) {
  236.      return;
  237.       }
  238.       /* depth buffering w/ stencil */
  239.       gl_depth_stencil_span( n, x, y, z, mask );
  240.    }
  241.    else if (CC.Depth.Test) {
  242.       /* regular depth testing */
  243.       if (gl_depth_test_span( n, x, y, z, mask )==0)  return;
  244.    }
  245.  
  246.    if (CC.Color.IndexMask==0) {
  247.       /* write no pixels */
  248.       return;
  249.    }
  250.  
  251.    /* logic op */
  252.    if (CC.Color.SWLogicOpEnabled) {
  253.       gl_logic_span( n, x, y, index, mask );
  254.    }
  255.  
  256.    if (CC.Color.SWmasking) {
  257.       gl_mask_index_span( n, x, y, index );
  258.    }
  259.  
  260.    /* write pixels */
  261.    (*DD.write_index_span)( n, x, y, index, mask );
  262. }
  263.  
  264.  
  265.  
  266.  
  267. void gl_write_monoindex_span( GLuint n, GLint x, GLint y, GLint z[],
  268.                   GLuint index, GLenum primitive )
  269. {
  270.    GLuint i;
  271.    GLubyte mask[MAX_WIDTH];
  272.  
  273.    /* init mask to 1's (all pixels are to be written) */
  274.    for (i=0;i<n;i++)
  275.       mask[i] = 1;
  276.  
  277.    if (CC.ClipSpans || primitive==GL_BITMAP) {
  278.       if (clip_span(n,x,y,mask)==0) {
  279.      return;
  280.       }
  281.    }
  282.  
  283.    /* Do the scissor test */
  284.    if (CC.Scissor.Enabled) {
  285.       if (gl_scissor_span( n, x, y, mask )==0) {
  286.      return;
  287.       }
  288.    }
  289.  
  290.    /* Polygon Stippling */
  291.    if (CC.Polygon.StippleFlag && primitive==GL_POLYGON) {
  292.       stipple_polygon_span( n, x, y, mask );
  293.    }
  294.  
  295.    if (CC.Stencil.Enabled) {
  296.       /* first stencil test */
  297.       if (gl_stencil_span( n, x, y, mask )==0) {
  298.      return;
  299.       }
  300.       /* depth buffering w/ stencil */
  301.       gl_depth_stencil_span( n, x, y, z, mask );
  302.    }
  303.    else if (CC.Depth.Test) {
  304.       /* regular depth testing */
  305.       if (gl_depth_test_span( n, x, y, z, mask )==0)  return;
  306.    }
  307.  
  308.    if (CC.Color.IndexMask==0) {
  309.       /* write no pixels */
  310.       return;
  311.    }
  312.  
  313.    if ((CC.Fog.Enabled && (CC.Hint.Fog==GL_NICEST || primitive==GL_BITMAP))
  314.         || CC.Color.SWLogicOpEnabled || CC.Color.SWmasking) {
  315.       GLuint ispan[MAX_WIDTH];
  316.       for (i=0;i<n;i++) {
  317.      ispan[i] = index;
  318.       }
  319.  
  320.       if (CC.Fog.Enabled && (CC.Hint.Fog==GL_NICEST || primitive==GL_BITMAP)) {
  321.      gl_fog_index_pixels( n, z, ispan );
  322.       }
  323.  
  324.       if (CC.Color.SWLogicOpEnabled) {
  325.      gl_logic_span( n, x, y, ispan, mask );
  326.       }
  327.  
  328.       if (CC.Color.SWmasking) {
  329.          gl_mask_index_span( n, x, y, ispan );
  330.       }
  331.  
  332.       (*DD.write_index_span)( n, x, y, ispan, mask );
  333.    }
  334.    else {
  335.       (*DD.write_monoindex_span)( n, x, y, mask );
  336.    }
  337. }
  338.  
  339.  
  340.  
  341. void gl_write_color_span( GLuint n, GLint x, GLint y, GLint z[],
  342.               GLubyte r[], GLubyte g[],
  343.               GLubyte b[], GLubyte a[],
  344.               GLenum primitive )
  345. {
  346.    GLuint i;
  347.    GLubyte mask[MAX_WIDTH];
  348.    GLboolean write_all = GL_TRUE;
  349.    GLubyte rtmp[MAX_WIDTH], gtmp[MAX_WIDTH], btmp[MAX_WIDTH], atmp[MAX_WIDTH];
  350.    GLubyte *red, *green, *blue, *alpha;
  351.  
  352.    /* init mask to 1's (all pixels are to be written) */
  353.    for (i=0;i<n;i++)
  354.       mask[i] = 1;
  355.  
  356.    if (CC.ClipSpans || primitive==GL_BITMAP) {
  357.       if (clip_span(n,x,y,mask)==0) {
  358.      return;
  359.       }
  360.       write_all = GL_FALSE;
  361.    }
  362.  
  363.    if (CC.MutableColors && primitive==GL_BITMAP) {
  364.       /* must make a copy of the colors since they can be modified */
  365.       MEMCPY( rtmp, r, n * sizeof(GLubyte) );
  366.       MEMCPY( gtmp, g, n * sizeof(GLubyte) );
  367.       MEMCPY( btmp, b, n * sizeof(GLubyte) );
  368.       MEMCPY( atmp, a, n * sizeof(GLubyte) );
  369.       red = rtmp;
  370.       green = gtmp;
  371.       blue = btmp;
  372.       alpha = atmp;
  373.    }
  374.    else {
  375.       red   = r;
  376.       green = g;
  377.       blue  = b;
  378.       alpha = a;
  379.    }
  380.  
  381.    /* Per-pixel fog */
  382.    if (CC.Fog.Enabled && (CC.Hint.Fog==GL_NICEST || primitive==GL_BITMAP)) {
  383.       gl_fog_color_pixels( n, z, red, green, blue, alpha );
  384.    }
  385.  
  386.    /* Do the scissor test */
  387.    if (CC.Scissor.Enabled) {
  388.       if (gl_scissor_span( n, x, y, mask )==0) {
  389.      return;
  390.       }
  391.       write_all = GL_FALSE;
  392.    }
  393.  
  394.    /* Polygon Stippling */
  395.    if (CC.Polygon.StippleFlag && primitive==GL_POLYGON) {
  396.       stipple_polygon_span( n, x, y, mask );
  397.       write_all = GL_FALSE;
  398.    }
  399.  
  400.    /* Do the alpha test */
  401.    if (CC.Color.AlphaEnabled) {
  402.       if (gl_alpha_test( n, alpha, mask )==0) {
  403.      return;
  404.       }
  405.       write_all = GL_FALSE;
  406.    }
  407.  
  408.    if (CC.Stencil.Enabled) {
  409.       /* first stencil test */
  410.       if (gl_stencil_span( n, x, y, mask )==0) {
  411.      return;
  412.       }
  413.       /* depth buffering w/ stencil */
  414.       gl_depth_stencil_span( n, x, y, z, mask );
  415.       write_all = GL_FALSE;
  416.    }
  417.    else if (CC.Depth.Test) {
  418.       /* regular depth testing */
  419.       GLuint m = gl_depth_test_span( n, x, y, z, mask );
  420.       if (m==0) {
  421.          return;
  422.       }
  423.       if (m<n) {
  424.          write_all = GL_FALSE;
  425.       }
  426.    }
  427.  
  428.    if (CC.Color.ColorMask==0) {
  429.       /* write no pixels */
  430.       return;
  431.    }
  432.  
  433.    if (CC.RasterMask & GAMMA_BIT) {
  434.       gl_apply_gamma( n, red, green, blue );
  435.    }
  436.  
  437.    /* blending */
  438.    if (CC.Color.BlendEnabled) {
  439.       gl_blend_span( n, x, y, red, green, blue, alpha, mask );
  440.    }
  441.  
  442.    /* Color component masking */
  443.    if (CC.Color.SWmasking) {
  444.       gl_mask_color_span( n, x, y, red, green, blue, alpha );
  445.    }
  446.  
  447.    /* write pixels */
  448.    (*DD.write_color_span)( n, x, y, red, green, blue, alpha,
  449.                            write_all ? NULL : mask );
  450. }
  451.  
  452.  
  453.  
  454. /*
  455.  * Write a horizontal span of color pixels to the frame buffer.
  456.  * The color is initially constant for the whole span.
  457.  * Alpha-testing, stenciling, depth-testing, and blending are done as needed.
  458.  * Input:  n - number of pixels in the span
  459.  *         x, y - location of leftmost pixel in the span
  460.  *         z - array of [n] z-values
  461.  *         color - the color to use.
  462.  *         primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
  463.  */
  464. void gl_write_monocolor_span( GLuint n, GLint x, GLint y, GLint z[],
  465.                   GLfloat color[4], GLenum primitive )
  466. {
  467.    GLuint i;
  468.    GLubyte mask[MAX_WIDTH];
  469.    GLboolean write_all = GL_TRUE;
  470.  
  471.    /* init mask to 1's (all pixels are to be written) */
  472.    for (i=0;i<n;i++)
  473.       mask[i] = 1;
  474.  
  475.    if (CC.ClipSpans || primitive==GL_BITMAP) {
  476.       if (clip_span(n,x,y,mask)==0) {
  477.      return;
  478.       }
  479.       write_all = GL_FALSE;
  480.    }
  481.  
  482.    /* Do the scissor test */
  483.    if (CC.Scissor.Enabled) {
  484.       if (gl_scissor_span( n, x, y, mask )==0) {
  485.      return;
  486.       }
  487.       write_all = GL_FALSE;
  488.    }
  489.  
  490.    /* Polygon Stippling */
  491.    if (CC.Polygon.StippleFlag && primitive==GL_POLYGON) {
  492.       stipple_polygon_span( n, x, y, mask );
  493.       write_all = GL_FALSE;
  494.    }
  495.  
  496.    /* Do the alpha test */
  497.    if (CC.Color.AlphaEnabled) {
  498.       GLubyte alpha[MAX_WIDTH];
  499.       for (i=0;i<n;i++) {
  500.          alpha[i] = (GLint) (color[3] * CC.AlphaScale);
  501.       }
  502.       if (gl_alpha_test( n, alpha, mask )==0) {
  503.      return;
  504.       }
  505.       write_all = GL_FALSE;
  506.    }
  507.  
  508.    if (CC.Stencil.Enabled) {
  509.       /* first stencil test */
  510.       if (gl_stencil_span( n, x, y, mask )==0) {
  511.      return;
  512.       }
  513.       /* depth buffering w/ stencil */
  514.       gl_depth_stencil_span( n, x, y, z, mask );
  515.       write_all = GL_FALSE;
  516.    }
  517.    else if (CC.Depth.Test) {
  518.       /* regular depth testing */
  519.       GLuint m = gl_depth_test_span( n, x, y, z, mask );
  520.       if (m==0) {
  521.          return;
  522.       }
  523.       if (m<n) {
  524.          write_all = GL_FALSE;
  525.       }
  526.    }
  527.  
  528.    if (CC.Color.ColorMask==0) {
  529.       /* write no pixels */
  530.       return;
  531.    }
  532.  
  533.    if (CC.Color.BlendEnabled || CC.Color.SWmasking
  534.        || (CC.RasterMask & GAMMA_BIT)) {
  535.       /* assign same color to each pixel */
  536.       GLubyte red[MAX_WIDTH], green[MAX_WIDTH];
  537.       GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];
  538.       register GLint r, g, b, a;
  539.       r = (GLubyte) (GLint) (color[0] * CC.RedScale);
  540.       g = (GLubyte) (GLint) (color[1] * CC.GreenScale);
  541.       b = (GLubyte) (GLint) (color[2] * CC.BlueScale);
  542.       a = (GLubyte) (GLint) (color[3] * CC.AlphaScale);
  543.       for (i=0;i<n;i++) {
  544.      if (mask[i]) {
  545.         red[i]   = r;
  546.         green[i] = g;
  547.         blue[i]  = b;
  548.         alpha[i] = a;
  549.      }
  550.       }
  551.  
  552.       if (CC.RasterMask & GAMMA_BIT) {
  553.          gl_apply_gamma( n, red, green, blue );
  554.       }
  555.  
  556.       if (CC.Color.BlendEnabled) {
  557.          gl_blend_span( n, x, y, red, green, blue, alpha, mask );
  558.       }
  559.  
  560.       /* Color component masking */
  561.       if (CC.Color.SWmasking) {
  562.          gl_mask_color_span( n, x, y, red, green, blue, alpha );
  563.       }
  564.  
  565.       /* write pixels */
  566.       (*DD.write_color_span)( n, x, y, red, green, blue, alpha,
  567.                               write_all ? NULL : mask );
  568.    }
  569.    else {
  570.       (*DD.write_monocolor_span)( n, x, y, mask );
  571.    }
  572. }
  573.  
  574.  
  575.  
  576. /*
  577.  * Write a horizontal span of textured pixels to the frame buffer.
  578.  * The color of each pixel is different.
  579.  * Alpha-testing, stenciling, depth-testing, and blending are done
  580.  * as needed.
  581.  * Input:  n - number of pixels in the span
  582.  *         x, y - location of leftmost pixel in the span
  583.  *         z - array of [n] z-values
  584.  *         s, t - array of (s,t) texture coordinates for each pixel
  585.  *         red, green, blue, alpha - array of [n] color components
  586.  *         primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
  587.  */
  588. void gl_write_texture_span( GLuint n, GLint x, GLint y, GLint z[],
  589.                 GLfloat s[], GLfloat t[],
  590.                 GLubyte r[], GLubyte g[],
  591.                 GLubyte b[], GLubyte a[],
  592.                 GLenum primitive )
  593. {
  594.    GLuint i;
  595.    GLubyte mask[MAX_WIDTH];
  596.    GLboolean write_all = GL_TRUE;
  597.    GLubyte rtmp[MAX_WIDTH], gtmp[MAX_WIDTH], btmp[MAX_WIDTH], atmp[MAX_WIDTH];
  598.    GLubyte *red, *green, *blue, *alpha;
  599.  
  600.    /* init mask to 1's (all pixels are to be written) */
  601.    for (i=0;i<n;i++)
  602.       mask[i] = 1;
  603.  
  604.    if (CC.ClipSpans || primitive==GL_BITMAP) {
  605.       if (clip_span(n,x,y,mask)==0) {
  606.      return;
  607.       }
  608.       write_all = GL_FALSE;
  609.    }
  610.  
  611.  
  612.    if (primitive==GL_BITMAP) {
  613.       /* must make a copy of the colors since they can be modified */
  614.       MEMCPY( rtmp, r, n * sizeof(GLubyte) );
  615.       MEMCPY( gtmp, g, n * sizeof(GLubyte) );
  616.       MEMCPY( btmp, b, n * sizeof(GLubyte) );
  617.       MEMCPY( atmp, a, n * sizeof(GLubyte) );
  618.       red = rtmp;
  619.       green = gtmp;
  620.       blue = btmp;
  621.       alpha = atmp;
  622.    }
  623.    else {
  624.       red   = r;
  625.       green = g;
  626.       blue  = b;
  627.       alpha = a;
  628.    }
  629.  
  630.    /* Texture */
  631.    if (CC.Texture.Enabled & 2) {
  632.       gl_texture_pixels_2d( n, s, t, red, green, blue, alpha );
  633.    }
  634.    else if (CC.Texture.Enabled & 1) {
  635.       gl_texture_pixels_1d( n, s, red, green, blue, alpha );
  636.    }
  637.  
  638.  
  639.    /* Per-pixel fog */
  640.    if (CC.Fog.Enabled && (CC.Hint.Fog==GL_NICEST || primitive==GL_BITMAP)) {
  641.       gl_fog_color_pixels( n, z, red, green, blue, alpha );
  642.    }
  643.  
  644.    /* Do the scissor test */
  645.    if (CC.Scissor.Enabled) {
  646.       if (gl_scissor_span( n, x, y, mask )==0) {
  647.      return;
  648.       }
  649.       write_all = GL_FALSE;
  650.    }
  651.  
  652.    /* Polygon Stippling */
  653.    if (CC.Polygon.StippleFlag && primitive==GL_POLYGON) {
  654.       stipple_polygon_span( n, x, y, mask );
  655.       write_all = GL_FALSE;
  656.    }
  657.  
  658.    /* Do the alpha test */
  659.    if (CC.Color.AlphaEnabled) {
  660.       if (gl_alpha_test( n, alpha, mask )==0) {
  661.      return;
  662.       }
  663.       write_all = GL_FALSE;
  664.    }
  665.  
  666.    if (CC.Stencil.Enabled) {
  667.       /* first stencil test */
  668.       if (gl_stencil_span( n, x, y, mask )==0) {
  669.      return;
  670.       }
  671.       /* depth buffering w/ stencil */
  672.       gl_depth_stencil_span( n, x, y, z, mask );
  673.       write_all = GL_FALSE;
  674.    }
  675.    else if (CC.Depth.Test) {
  676.       /* regular depth testing */
  677.       GLuint m = gl_depth_test_span( n, x, y, z, mask );
  678.       if (m==0) {
  679.          return;
  680.       }
  681.       if (m<n) {
  682.          write_all = GL_FALSE;
  683.       }
  684.    }
  685.  
  686.    if (CC.Color.ColorMask==0) {
  687.       /* write no pixels */
  688.       return;
  689.    }
  690.  
  691.    if (CC.RasterMask & GAMMA_BIT) {
  692.       gl_apply_gamma( n, red, green, blue );
  693.    }
  694.  
  695.    /* blending */
  696.    if (CC.Color.BlendEnabled) {
  697.       gl_blend_span( n, x, y, red, green, blue, alpha, mask );
  698.    }
  699.  
  700.    if (CC.Color.SWmasking) {
  701.       gl_mask_color_span( n, x, y, red, green, blue, alpha );
  702.    }
  703.  
  704.    /* write pixels */
  705.    (*DD.write_color_span)( n, x, y, red, green, blue, alpha,
  706.                            write_all ? NULL : mask );
  707. }
  708.  
  709.  
  710.  
  711. /*
  712.  * Read RGBA pixels from frame buffer.  Clipping will be done to prevent
  713.  * reading ouside the buffer's boundaries.
  714.  */
  715. void gl_read_color_span( GLuint n, GLint x, GLint y,
  716.              GLubyte red[], GLubyte green[],
  717.              GLubyte blue[], GLubyte alpha[] )
  718. {
  719.    register GLuint i;
  720.  
  721.    if (y<0 || y>=CC.BufferHeight || x>=CC.BufferWidth) {
  722.       /* completely above, below, or right */
  723.       for (i=0;i<n;i++) {
  724.      red[i] = green[i] = blue[i] = alpha[i] = 0;
  725.       }
  726.    }
  727.    else {
  728.       if (x>=0 && x+n<=CC.BufferWidth) {
  729.      /* OK */
  730.      (*DD.read_color_span)( n, x, y, red, green, blue, alpha );
  731.       }
  732.       else {
  733.      i = 0;
  734.      if (x<0) {
  735.         while (x<0 && n>0) {
  736.            red[i] = green[i] =  blue[i] = alpha[i] = 0;
  737.            x++;
  738.            n--;
  739.            i++;
  740.         }
  741.      }
  742.      n = MIN2( n, CC.BufferWidth - x );
  743.      (*DD.read_color_span)( n, x, y, red+i, green+i, blue+i, alpha+i );
  744.       }
  745.    }
  746. }
  747.  
  748.  
  749.  
  750.  
  751. /*
  752.  * Read CI pixels from frame buffer.  Clipping will be done to prevent
  753.  * reading ouside the buffer's boundaries.
  754.  */
  755. void gl_read_index_span( GLuint n, GLint x, GLint y, GLuint indx[] )
  756. {
  757.    register GLuint i;
  758.  
  759.    if (y<0 || y>=CC.BufferHeight || x>=CC.BufferWidth) {
  760.       /* completely above, below, or right */
  761.       for (i=0;i<n;i++) {
  762.      indx[i] = 0;
  763.       }
  764.    }
  765.    else {
  766.       if (x>=0 && x+n<=CC.BufferWidth) {
  767.      /* OK */
  768.      (*DD.read_index_span)( n, x, y, indx );
  769.       }
  770.       else {
  771.      i = 0;
  772.      if (x<0) {
  773.         while (x<0 && n>0) {
  774.            indx[i] = 0;
  775.            x++;
  776.            n--;
  777.            i++;
  778.         }
  779.      }
  780.      n = MIN2( n, CC.BufferWidth - x );
  781.      (*DD.read_index_span)( n, x, y, indx+i );
  782.       }
  783.    }
  784. }
  785.  
  786.  
  787.